/**
 * @class   wosh::ISerializable
 * @brief   
 *
 *
 * \par Framework Developers Notes
 *  - KNOWN PROBLEM
 *    regarding virtual inheritance and Covariant Return Types on MSVC (9.0 and previous)
 * \verbatim
// virtual ISerializable ==>> MSC CRASH on clone() cos of wrong member pointer!!
// QUESTION: is it a MSVC BUG??? (it looks like!, G++ works fine as espected)
class MessageContent : public ISerializable 		//<  OK
class MessageContent : public virtual ISerializable	//<  BUG on MSVC
\endverbatim
 *
 *
 ****************************************************************************
 * @version 0.8.399 $Id: Serialization.h 2789 2010-07-23 11:47:27Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_Serialization_H__
 #define __WOSH_Core_Serialization_H__

 #include <woshDefs.h>
 #include <core/Reflection.h>
 #include <core/DataHash.h>


namespace wosh {


// so you can call Super::do_superclass_implementation (in generic way)
# undef WOSH_SUPER
# define WOSH_SUPER(CLASSNAME)											\
		public: typedef CLASSNAME Super;


// suppose Covariant Return Types
// else: public: virtual ISerializable* clone() const { return new CLASSNAME(*this); }

#ifdef _USE_COVARIANT_RETURN_TYPE
# undef WOSH_CLONE_CONSTRUCTOR
# define WOSH_CLONE_CONSTRUCTOR(CLASSNAME)											\
		public: virtual CLASSNAME* clone() const { return new CLASSNAME(*this); }

# undef WOSH_CLONE_ABSTRACT
# define WOSH_CLONE_ABSTRACT(CLASSNAME)												\
		public: virtual CLASSNAME* clone() const = 0;
#endif


#undef WOSH_COPY_FORBIDDEN
#define WOSH_COPY_FORBIDDEN(CLASSNAME)												\
		private: CLASSNAME(const CLASSNAME&) { }									\
		private: CLASSNAME& operator=(const CLASSNAME&) { return *this; }			\
		public: virtual CLASSNAME* clone() const { return NULL; }


# define WOSH_COMPARE_RET_IDEMPOTENT		0
# define WOSH_COMPARE_RET_NOT_EQUAL			1
# define WOSH_COMPARE_RET_MINOR				3
# define WOSH_COMPARE_RET_MAYOR				5
# define WOSH_COMPARE_RET_CAST_INVALID		131
# define WOSH_COMPARE_MASK_ANY				255

#ifdef _USE_RTTI
# undef WOSH_COMPARE_RTTI
# define WOSH_COMPARE_RTTI(CLASSNAME)												\
		public: virtual int compare(const wosh::ISerializable* other) const {		\
			const CLASSNAME* other_c = dynamic_cast<const CLASSNAME*>(other);		\
			if ( other_c == NULL ) return WOSH_COMPARE_RET_CAST_INVALID;			\
			if ( *this == *other_c ) return WOSH_COMPARE_RET_IDEMPOTENT;			\
			return WOSH_COMPARE_RET_NOT_EQUAL;										\
		 }

# undef WOSH_COMPAREX_RTTI
# define WOSH_COMPAREX_RTTI(CLASSNAME)												\
		public: virtual int compare(const wosh::ISerializable* other) const {		\
			const CLASSNAME* other_c = dynamic_cast<const CLASSNAME*>(other);		\
			if ( other_c == NULL ) return WOSH_COMPARE_RET_CAST_INVALID;			\
			if ( *this == *other_c ) return WOSH_COMPARE_RET_IDEMPOTENT;			\
			if ( *this < *other_c ) return WOSH_COMPARE_RET_MINOR;					\
			if ( *this > *other_c ) return WOSH_COMPARE_RET_MAYOR;					\
			return WOSH_COMPARE_RET_NOT_EQUAL;										\
		 }
#endif //_USE_RTTI



// implements:
// ALL from IReflection; IsAbstract() = false
// clone() based on copy-constructor

#undef WOSH_SERIALIZABLE
#define WOSH_SERIALIZABLE(CLASSNAME)			\
		WOSH_CLASSNAME(CLASSNAME)				\
		WOSH_CLASS_ABSTRACT(false)				\
												\
		WOSH_CLONE_CONSTRUCTOR(CLASSNAME)

#undef WOSH_SERIALIZABLE_ABSTRACT
#define WOSH_SERIALIZABLE_ABSTRACT(CLASSNAME)	\
		WOSH_CLASSNAME(CLASSNAME)				\
		WOSH_CLASS_ABSTRACT(true)				\
												\
		WOSH_CLONE_ABSTRACT(CLASSNAME)


/*
class IComparable {
	virtual int compare( const ISerializable* other ) const = 0;

};
*/


class ISerializable : public virtual IReflection
 {
//	WOSH_CLASSNAME(wosh::ISerializable) // this can cause more bugs and benefits
	WOSH_CLASS_ABSTRACT(true)

/** @name Serialization Interface
 * @{
 ******************************************************************************/
	public:
		/**
		 * @brief  Create a cloned object.
		 * @return pointer to the new object, caller must care about de-allocation
		 * @see    WOSH_CLONE
		 */
		virtual ISerializable* clone() const = 0;   // The Virtual (Copy) Constructor

		template <typename T>
		inline T* clone() const {
			return dynamic_cast<T*>( this->clone() );
		 }

		/**
		 * @brief  Compare object against another of same type.
		 * @param other [in] the object to be compared
		 * @return when object are identical return 0; return -1 when object are of different types
		 * @see    WOSH_COMPARE_RTTI
		 */
		virtual int compare( const ISerializable* other ) const = 0;

		/**
		 * @brief  Get  object minimal (not full!) representation.
		 * @return usually object's name or value
		 */
		virtual std::string toString() const = 0;


		virtual bool updateHash( DataHashContext* hash_context ) const = 0;


//@}
	public:
		virtual ~ISerializable() { }

}; // class def


}; // namespace wosh

#endif //__WOSH_Core_Serialization_H__
